package cn.yitun.chat.yitunserverrunsingleboot.startup;

import cn.yitun.chat.yitunserverrunsingleboot.chat.common.app.JwtUserResolver;
import cn.yitun.chat.yitunserverrunsingleboot.chat.common.interceptor.SessionInterceptor;
import cn.yitun.chat.yitunserverrunsingleboot.chat.common.interceptor.TokenInterceptor;
import cn.yitun.chat.yitunserverrunsingleboot.chat.properties.ServerProperties;
import cn.yitun.chat.yitunspringweb.web.resolver.JsonDefineResolver;
import cn.yitun.chat.yitunspringweb.web.resolver.ParamDefineResolver;
import cn.yitun.chat.yitunspringweb.web.resolver.ParameterBeanResolver;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.*;

import javax.annotation.Resource;
import javax.servlet.MultipartConfigElement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * WebConfig WebServlet配置类 spring mvc 配置
 */
@Configuration
// @EnableWebMvc
// @ComponentScan(basePackages = "com.only.chat", useDefaultFilters = false,
// includeFilters = { @ComponentScan.Filter(value = { Controller.class }) })
public class WebConfig implements WebMvcConfigurer {

	@Resource
	private ServerProperties serverProperties;

	@Resource
	private TokenInterceptor tokenInterceptor;

	@Override
	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {

//		argumentResolvers.add(beanDefineResolver());
		argumentResolvers.add(jsonDefineResolver());
		argumentResolvers.add(paramDefineResolver());
		argumentResolvers.add(parameterBeanResolver());
		argumentResolvers.add(jwtUserResolver()); //将head中jwtToken解析封装
	}

//	@Bean
//	public BeanDefineResolver beanDefineResolver() {
//		return new BeanDefineResolver();
//	}

	@Bean
	public JsonDefineResolver jsonDefineResolver() {
		return new JsonDefineResolver();
	}

	@Bean
	public ParamDefineResolver paramDefineResolver() {
		return new ParamDefineResolver();
	}

	/**
	 * 只处理采用application/x-www-form-urlencoded形式入参，封装javabean
	 * @return
	 */
	@Bean
	public ParameterBeanResolver parameterBeanResolver() {
		return new ParameterBeanResolver();
	}

	@Bean
	public LocalValidatorFactoryBean localValidatorFactoryBean() {
		return new LocalValidatorFactoryBean();
	}

	@Bean
	public JwtUserResolver jwtUserResolver() {
		return new JwtUserResolver();
	}
	

	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
		configurer.mediaType("json", MediaType.APPLICATION_JSON);
	}

	/**
	 * 国际化处理
	 *
	 * @return
	 */
	@Bean
	public MessageSource messageSource() {
		ResourceBundleMessageSource bean = new ResourceBundleMessageSource();
		bean.setBasename("property.message");
		bean.setCacheSeconds(3000);
		bean.setUseCodeAsDefaultMessage(true);
		return bean;
	}

	/**
	 * json消息转换适配器，用于支持RequestBody、ResponseBody
	 *
	 * @return
	 */
	@Bean
	public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {
		objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
		// 设置 SerializationFeature.FAIL_ON_EMPTY_BEANS 为 false
		objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

		List<MediaType> mediaTypeList = new ArrayList<MediaType>();
		mediaTypeList.add(MediaType.APPLICATION_JSON);
		mediaTypeList.add(MediaType.APPLICATION_JSON_UTF8);
		MappingJackson2HttpMessageConverter bean = new MappingJackson2HttpMessageConverter();
		bean.setObjectMapper(objectMapper);
		bean.setSupportedMediaTypes(mediaTypeList);
		return bean;
	}

	/**
	 * 附件Multipart解决方案
	 *
	 * @return
	 */
	// @Bean
	// public CommonsMultipartResolver multipartResolver() {
	// CommonsMultipartResolver bean = new CommonsMultipartResolver();
	// bean.setDefaultEncoding("utf-8");
	// bean.setMaxUploadSize(102400000);
	// return bean;
	// }

	@Bean
	MultipartConfigElement multipartConfigElement() {
		MultipartConfigFactory factory = new MultipartConfigFactory();
		// factory.setLocation("temp");
		factory.setMaxFileSize(1024L * 1024L * 1000L);
		return factory.createMultipartConfig();
	}

	@Bean
	public Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean() {
		Jackson2ObjectMapperFactoryBean bean = new Jackson2ObjectMapperFactoryBean();
		bean.setIndentOutput(true);
		bean.setSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return bean;
	}
	@Bean
	public HandlerInterceptor sessionInterceptor(){
		return new SessionInterceptor();
	}
	
	/**
	 * 添加资源控制器 遵循前后端分离
	 */
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry.addResourceHandler("/files/**").addResourceLocations("file:///" + serverProperties.getFileUploadPath());
//		registry.addResourceHandler("/manager-service/**").addResourceLocations("");
//		registry.addResourceHandler("/tcp-service/**").addResourceLocations("");
//		registry.addResourceHandler("/chat-service/**").addResourceLocations("");
//		registry.addResourceHandler("/remote-service/**").addResourceLocations("");
//		registry.addResourceHandler("/udp-service/**").addResourceLocations("");
	}

	/**
	 * 添加拦截器
	 * @param registry
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(tokenInterceptor)
				.addPathPatterns("/**")
				.excludePathPatterns(
						"/"
						, "/files/**"
						, "/common/sysFile/download"
						, "/manage/index/login"
						, "/manage/account/**"
						, "/api/chat/server/addressList"
						, "/manage/util/**"
				)
		;
//        registry.addInterceptor(apolloInterceptor)
//                .addPathPatterns("/apollo/**");
	}

	@Override
	public void addCorsMappings(CorsRegistry registry) {
		registry.addMapping("/**")
				.allowedOrigins("*")
				.allowedMethods("GET", "POST", "OPTIONS")
				.allowCredentials(false).maxAge(3600);
	}
}
